// Copyright 2011 Google Inc. All Rights Reserved.
// Author: jacobsa@google.com (Aaron Jacobs)
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

var fi = flame.internal;
var processResolveWorkItem = fi.processResolveWorkItem;

//////////////////////////////////////////////////////
// Helpers
//////////////////////////////////////////////////////

// Compare actions by reference.
flame.Action.gjstestEquals = function(other) { return this === other; };

function makeItem(actionNames, callback) {
  return { 'actionNames': actionNames, 'callback': callback };
}

function ProcessResolveWorkItemTest() {
  this.processPackage_ = createMockFunction('processPackage');

  this.workItem_ =
      { callback: createMockFunction('callback'), actionNames: [] };

  this.registeredActions_ = new fi.StringMap;
  this.packagesProcessed_ = new fi.StringSet;

  // Convenience function.
  var me = this;
  this.makeCall_ = function() {
    return processResolveWorkItem(
        me.workItem_,
        me.registeredActions_,
        me.packagesProcessed_,
        me.processPackage_);
  };
}
registerTestSuite(ProcessResolveWorkItemTest);

//////////////////////////////////////////////////////
// Tests
//////////////////////////////////////////////////////

ProcessResolveWorkItemTest.prototype.NoActionNames = function() {
  expectCall(this.workItem_.callback)(recursivelyEquals({}));
  expectThat(this.makeCall_(), elementsAre([true, true]));
};

ProcessResolveWorkItemTest.prototype.AllDepsAlreadyRegistered =
    function() {
  // Deps
  this.workItem_.actionNames.push('foo:taco');
  this.workItem_.actionNames.push('bar:burrito');

  // Actions -- all present.
  var taco = new flame.Action('foo:taco');
  var burrito = new flame.Action('bar:burrito');

  this.registeredActions_.insert(taco.name, taco);
  this.registeredActions_.insert(burrito.name, burrito);

  this.packagesProcessed_.insert('foo');
  this.packagesProcessed_.insert('bar');

  // Callback
  expectCall(this.workItem_.callback)(
      recursivelyEquals({
          'foo:taco': taco,
          'bar:burrito': burrito,
      }));

  // Call
  expectThat(this.makeCall_(), elementsAre([true, true]));
};

ProcessResolveWorkItemTest.prototype.OneDepNonExistent = function() {
  // Deps
  this.workItem_.actionNames.push('foo:taco');
  this.workItem_.actionNames.push('bar:burrito');
  this.workItem_.actionNames.push('baz:enchilada');

  // Actions -- bar:burrito missing.
  var taco = new flame.Action('foo:taco');
  var enchilada = new flame.Action('baz:enchilada');

  this.registeredActions_.insert(taco.name, taco);
  this.registeredActions_.insert(enchilada.name, enchilada);

  this.packagesProcessed_.insert('foo');
  this.packagesProcessed_.insert('bar');
  this.packagesProcessed_.insert('baz');

  // Call
  expectThat(this.makeCall_(), elementsAre([false, false]));
};

ProcessResolveWorkItemTest.prototype.PackagesWaitingToBeProcessed = function() {
  // Deps
  this.workItem_.actionNames.push('foo:taco');
  this.workItem_.actionNames.push('bar:burrito');
  this.workItem_.actionNames.push('baz:enchilada');

  // Actions -- bar:burrito and baz:enchilada missing.
  var taco = new flame.Action('foo:taco');
  this.registeredActions_.insert(taco.name, taco);

  this.packagesProcessed_.insert('foo');

  // processPackage
  expectCall(this.processPackage_)('bar');
  expectCall(this.processPackage_)('baz');

  // Call
  expectThat(this.makeCall_(), elementsAre([false, true]));
};

ProcessResolveWorkItemTest.prototype.DuplicatePackagesPending = function() {
  // Deps
  this.workItem_.actionNames.push('foo:taco');
  this.workItem_.actionNames.push('bar:burrito');
  this.workItem_.actionNames.push('baz:enchilada');
  this.workItem_.actionNames.push('baz:queso');
  this.workItem_.actionNames.push('bar:tortilla');

  // Actions -- only foo ones present.
  var taco = new flame.Action('foo:taco');
  this.registeredActions_.insert(taco.name, taco);

  this.packagesProcessed_.insert('foo');

  // processPackage
  expectCall(this.processPackage_)('bar');
  expectCall(this.processPackage_)('baz');

  // Call
  expectThat(this.makeCall_(), elementsAre([false, true]));
};
